﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//so it begins // and it ends :)
class Game
{
    public const int ConsoleWidthMax = 123;
    public const int ConsoleHeightMax = 78;

    //the ONLY random generator
    public static Random rnd = new Random();

    
    public static List<Shot> Shots = new List<Shot>(); //list of shtos

    //public static int Player; //player structure
    public static Player player;

    //obsticals - poli
    public static List<Obstacle> obstacles = new List<Obstacle>();

    //game settings
    public static int gameSpeed = 975;//the higher the faster//975 is farely good
    public static ConsoleKey MoveUp = ConsoleKey.UpArrow;
    public static ConsoleKey MoveDown = ConsoleKey.DownArrow;
    public static ConsoleKey MoveLeft = ConsoleKey.LeftArrow;
    public static ConsoleKey MoveRight = ConsoleKey.RightArrow;
    public static ConsoleKey Shoot = ConsoleKey.Spacebar;
    public static ConsoleKey Pause = ConsoleKey.P;
    public static int playerTotalScore = 0;
    public static int time = 0;
    public static int maxShots = 5;
    public static int reloadTime = 0;
    public static int level = 0;// holds the current difficulty level

    //enemies
    public static int enemyScoreGivvenForKillingCoordinatorEnemy = 10; //score gain when killing different enemies
    public static int enemyScoreGivvenForKillingNormalEnemy = 5;       //score gain when killing different enemies
    public static int enemyScoreGivvenForKillingDummyEnemy = 2;        //score gain when killing different enemies
    public static int enemyhardness = 2;//1 or more //part of gamesettings//In use now - how much bullets does it take to kill an enemy
    public static int enemyNormal = 4;               //part of gamesettings//the realCount is = 4 * (value / 4);
    public static int enemyDummies = 4;             //part of gamesettings //the realCount is = 4 * (value / 4);
    public static int enemyTargetX;//holds the last targeted position of the player.
    public static int enemyTargetY;//holds the last targeted position of the player.
    public static string[] enemyCoordinatorTalks = new string[] { "DIE!", "KILL", "ARGH", "HAHA" };//what does the coordinator say
    public static int enemyCoordinatorTargetFrequency = 40;//how often does the coordinator target you
    public static int enemyCoordinatorTargetTimer = 1000;//how often does the coordinator target you
    public static int[] enemyCoordinatorCoordinates;//needs to know where the coordinator is so he can talk
    public static int enemyMoveCounter = 2;//how often (fast) the enemy move //in this case (4) it will have to get to 0 to move
    public static int enemyMoveFactor = 1; //how often (fast) the enemy move //each time we substract (1) from the counter
    public static bool enemyCoordinatorIsAlive = true;//if he is alive he will target player,otherwise enemies are blind
    public static bool enemyWantToScreamIfTheirBossIsDead = true;//when coordinator dies enemies yell only once
    public static bool enemyInitialTargeting = true;//at the start of the game enemies will target you
    public static int enemyCoordinatorRespawnTime = 1000;
    public static List<Enemy> enemies = new List<Enemy>();//holds all the enemies

    //Main
    static void Main()
    {
        ConsoleSetUp();
        MainMenu();
    }

    private static void ConsoleSetUp()
    {
        Console.WindowWidth = ConsoleWidthMax;
        Console.WindowHeight = ConsoleHeightMax;
        Console.BufferWidth = ConsoleWidthMax;
        Console.BufferHeight = ConsoleHeightMax;

        Console.BackgroundColor = ConsoleColor.Black;
        Console.Title = "\"SHE HULK\" GAME";
    }

    public static void MainMenu()
    {

        int choice = Menu.StartMenu();
        switch (choice)
        {
            case 0:
                {
                    RunGame();//test
                    return;
                }
            case 1: Menu.Controls(); break;
            case 2: level = Menu.LevelMenu(1); Console.Clear(); break;
            case 3: Menu.HighScores(); break;
            case 4: Menu.Help(); break;
            case 5: Exit(); break;
            default: return;
        }
        MainMenu();//recursive menu update (krum)
    }

    public static void RunGame() 
    {
        Console.Clear();           //restarting the game
        enemies.Clear();           //restarting the game
        Shots.Clear();             //restarting the game
        obstacles.Clear();         //restarting the game

        GeneratePlayer();

        GenerateObstacles();

        player.DrawPlayerFace();

        GenerateEnemies();

        while (1 == 1)
        {
            time++;

            ReadConsoleKeys();

            ProcessShots();

            ProcessEnemies();

            PrintShots();

            System.Threading.Thread.Sleep(1000 - gameSpeed);
        }
    }

    public static void GeneratePlayer()
    {
        player = new Player();
        player.x = 60;
        player.y = 40;
    }
    public static void GenerateObstacles()
    {
        // obsX and obsY keep the coordinates (obsX - X(width); obsY - Y(height)) of points which will be used for generating obstacles.
        if (level % 2 == 0) 
        {           
            int[] obsX = { 10, 35, 77, 103, 25, 10, 51, 61, 87, 103, 18, 10, 33, 18, 60, 103, 87, 111, 103 }; // x - width
            int[] obsY = { 20, 15, 15, 20, 33, 55, 51, 51, 33, 55, 10, 22, 35, 57, 53, 10, 35, 45, 57 }; // y - height
            for (int k = 0; k < 10; k++)
            {
                GenerateObstaclesHorizontal(obsX[k], obsY[k]);
            }

            for (int k = 10; k < 19; k++)
            {
                GenerateObstaclesVertical(obsX[k], obsY[k]);
            }
        }
        else
        {
            int[] obsX = { 21, 31, 82, 92, 51, 61, 28, 85, 9, 104, 46, 66, 9, 9, 26, 36, 60, 95, 85, 112, 112 };
            int[] obsY = { 8, 8, 8, 8, 20, 20, 41, 41, 59, 59, 59, 59, 24, 61, 10, 43, 22, 10, 43, 24, 61 };
            for (int k = 0; k < 12; k++)
            {
                GenerateObstaclesHorizontal(obsX[k], obsY[k]);
            }

            for (int k = 12; k < 21; k++)
            {
                GenerateObstaclesVertical(obsX[k], obsY[k]);
            }
        }

        foreach (Obstacle obs in obstacles)
        {
            obs.DrawObstacles();
        }
    }

    private static void GenerateObstaclesVertical(int x, int y)
    {
        for (int i = x; i < x + 2; i++)
        {
            for (int j = y; j < y + 10; j++)
            {
                obstacles.Add(new Obstacle(i, j));
            }
        }
    }

    private static void GenerateObstaclesHorizontal(int x, int y)
    {
        for (int i = x; i < x + 10; i++)
        {
            for (int j = y; j < y + 2; j++)
            {
                obstacles.Add(new Obstacle(i, j));
            }
        }
    }

    private static void PrintShots()
    {
        List<Shot> newShots = new List<Shot>();

        foreach (var shot in Shots)
        {
            if (shot.alive)
            {
                shot.DrawShot(shot.X, shot.Y);
                newShots.Add(shot);
            }
        }
        Shots = newShots;
    }           
    
    private static void ProcessShots()
    {

        //Get shot coordinates and direction
        //

        //Add shot to shots list
        //Draw shot
        //Check if shot hits walls
        //Check if shot hits obstacles
        if (reloadTime > 0) reloadTime = reloadTime-level/3-1; //added reload time (krum)

        foreach (var shot in Shots)
        {
            shot.clearShot(shot.X, shot.Y);
            if (shot.direction == "Up")
            {
                shot.Y --;
                if (shot.Y < 1)
                {
                    shot.alive = false;
                }
                foreach (var obst in obstacles)
                {
                    if ((shot.X == obst.x) && (shot.Y == obst.y))
                    {
                        Console.Beep(400, 50);
                        shot.alive = false;
                        return;
                    }
                }

            }

            if (shot.direction == "Down")
            {
                shot.Y ++;
                if (shot.Y > ConsoleHeightMax - 1)
                {
                    shot.alive = false;
                }
                foreach (var obst in obstacles)
                {
                    if ((shot.X == obst.x) && (shot.Y == obst.y))
                    {
                        Console.Beep(400, 50);
                        shot.alive = false;
                        return;
                    }
                }
            }

            if (shot.direction == "Left")
            {
                shot.X --;
                if (shot.X < 1)
                {
                    shot.alive = false;
                }
                foreach (Obstacle obstacle in obstacles)
                {
                    if ((shot.Y == obstacle.y) && (shot.X == obstacle.x))
                    {
                        Console.Beep(400, 50);
                        shot.alive = false;
                        return;
                    }
                }

            }

            if (shot.direction == "Right")
            {
                shot.X ++;
                if (shot.X > ConsoleWidthMax - 1)
                {
                    shot.alive = false;
                }
                foreach (Obstacle obstacle in obstacles)
                {
                    if ((shot.Y == obstacle.y) && (shot.X == obstacle.x))
                    {
                        Console.Beep(400, 50);
                        shot.alive = false;
                        return;
                    }
                }
                //TO check for obstacles
            }
        }
    }         

    public static void Options()
    {
        //menu option 2
        //change controls
        //sound
    }

    public static void HighScores()
    {
        //menu option 3
        //get from text file
    }

    public static void Help()
    {
        //menu option 4
        //some useless stuff
    }

    public static void Exit()
    {
        Console.ForegroundColor = ConsoleColor.Black;
        Environment.Exit(0);
    }

    public static void ReadConsoleKeys()
    {
        if (Console.KeyAvailable)
        {
            ConsoleKeyInfo pressedKey = Console.ReadKey(true);
            while (Console.KeyAvailable)//improvement dzhenko for smoother movement
            {
                Console.ReadKey(true);
            }
            if (pressedKey.Key == Pause)
            {
                Console.Beep(3000, 1);
                Console.SetCursorPosition(43, 32);
                Console.WriteLine("Game Paused. Press 'P' to resume.");
                while (true)
                {
                    if (Console.KeyAvailable)
                    {
                        pressedKey = Console.ReadKey(true);
                        if (pressedKey.Key == ConsoleKey.P)
                        {
                            Console.SetCursorPosition(43, 32);
                            Console.WriteLine("                                 ");
                            Console.Beep(3000, 1);
                            return;
                        }
                    }
                }
            }
            else if (pressedKey.Key == MoveLeft)
            {
                foreach (var obst in obstacles)
                {
                    if (Math.Abs(player.y + 1 - obst.y) < 2 && (player.x - 1 == obst.x))
                    {
                        return;
                    }
                }
                Console.Beep(300, 1);
                player.Move("Left");
                player.DrawPlayerLeft();
             }
            else if (pressedKey.Key == MoveRight)
            {
                foreach (var obst in obstacles)
                {
                    if (Math.Abs(player.y + 1 - obst.y) < 2 && (player.x + 3 == obst.x))
                    {
                        return;
                    }
                }
                Console.Beep(300, 1);
                player.Move("Right");
                player.DrawPlayerRight();
            }
            else if (pressedKey.Key == MoveUp)
            {
                foreach (var obst in obstacles)
                {
                    if (Math.Abs(player.x + 1 - obst.x) < 2 && (player.y - 1 == obst.y))
                    {
                        return;
                    }
                }
                Console.Beep(300, 1);
                player.Move("Up");
                player.DrawPlayerBack();
            }
            else if (pressedKey.Key == MoveDown)
            {
                foreach (var obst in obstacles)
                {
                    if (Math.Abs(player.x + 1 - obst.x) < 2 && (player.y + 3 == obst.y))
                    {
                        return;
                    }
                }
                Console.Beep(300, 1);
                player.Move("Down");
                player.DrawPlayerFace();
            }
            else if (pressedKey.Key == Shoot)
            {
                
                Shot newShot = new Shot();

                if (reloadTime<1)//if (Shots.Count <= maxShots)
                {
                    reloadTime = 10;
                    Console.Beep(200, 30);
                    bool closeToWall = false;
                    if (player.direction == "Down")
                    {
                        if (player.y < ConsoleHeightMax)
                        {
                            newShot.X = player.x + 1;
                            newShot.Y = player.y + 3;
                            foreach (var obst in obstacles)
                            {
                                if (newShot.X == obst.x && newShot.Y == obst.y)
                                {
                                    closeToWall = true;
                                }
                            }
                            newShot.direction = player.direction;
                            newShot.alive = true;
                        }
                    }
                    if (player.direction == "Up")
                    {

                        if (player.y > 0)
                        {
                            newShot.X = player.x + 1;
                            newShot.Y = player.y - 1;
                            foreach (var obst in obstacles)
                            {
                                if (newShot.X == obst.x && newShot.Y == obst.y)
                                {
                                    closeToWall = true;
                                }
                            }
                            newShot.direction = player.direction;
                            newShot.alive = true;
                        }



                    }
                    if (player.direction == "Left")
                    {
                        foreach (var obst in obstacles)
                        {
                            if (Math.Abs(player.y + 1 - obst.y) < 2 && (player.x - 1 == obst.x))
                            {
                                return;
                            }
                        }
                        if (player.x > 0)
                        {
                            newShot.X = player.x - 1;
                            newShot.Y = player.y + 1;
                            foreach (var obst in obstacles)
                            {
                                if (newShot.X == obst.x && newShot.Y == obst.y)
                                {
                                    closeToWall = true;
                                }
                            }
                            newShot.direction = player.direction;
                            newShot.alive = true;
                        }

                    }
                    if (player.direction == "Right")
                    {
                        if (player.x < ConsoleWidthMax)
                        {
                            newShot.X = player.x + 3;
                            newShot.Y = player.y + 1;
                            foreach (var obst in obstacles)
                            {
                                if (newShot.X == obst.x && newShot.Y == obst.y)
                                {
                                    closeToWall = true;
                                }
                            }
                            newShot.direction = player.direction;
                            newShot.alive = true;
                        }
                    }

                    if (!closeToWall)
                    {
                        Shots.Add(newShot);
                    }
                    
                }

            }
        }
    }//krum

    private static void GameOver() // gameOptionsDesighner
    {
        Console.Beep(400, 150);
        Console.Clear();
        Console.SetCursorPosition(49, 13);
        Console.WriteLine("G A M E   O V E R");
        Menu.ScoreRecord(playerTotalScore, time);
        Console.Clear();
        MainMenu();
        //Environment.Exit(0);
    }

    private static void YouWin()
    {
        if (level == 5)
        {
            Console.Clear();
            Console.WriteLine("THATS THE END");
            Console.Clear();

            Menu.ScoreRecord(playerTotalScore, time);
        }
        level++;
        for (int i = 0; i < 3; i++)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.SetCursorPosition(ConsoleWidthMax / 2 - 20, ConsoleHeightMax / 2);
            Console.Write(" N E X T   L E V E L   I N : {0}",3-i);
            System.Threading.Thread.Sleep(1000);
        }
        RunGame();
        //Environment.Exit(0);
    }// gameOptionsDesighner


    /// <summary>
    /// dzhenko
    /// </summary>

    #region Enemies

    private static void ProcessGameDifficulty()
    {
        switch (level)
        {
            case 0:
                enemyDummies = 3;
                enemyNormal = 1;
                enemyhardness = 1;
                enemyCoordinatorTargetFrequency = 5;
                enemyMoveCounter = 20;
                break;
            case 1:
                enemyDummies = 4;
                enemyNormal = 2;
                enemyhardness = 2;
                enemyCoordinatorTargetFrequency = 8;
                enemyMoveCounter = 15;
                break;
            case 2:
                enemyDummies = 4;
                enemyNormal = 6;
                enemyhardness = 3;
                enemyCoordinatorTargetFrequency = 10;
                enemyMoveCounter = 12;
                break;
            case 3:
                enemyDummies = 6;
                enemyNormal = 10;
                enemyhardness = 4;
                enemyCoordinatorTargetFrequency = 12;
                enemyMoveCounter = 10;
                break;
            case 4:
                enemyDummies = 8;
                enemyNormal = 12;
                enemyhardness = 6;
                enemyCoordinatorTargetFrequency = 15;
                enemyMoveCounter = 8;
                break;
            case 5:
                enemyDummies = 10;
                enemyNormal = 16;
                enemyhardness = 10;
                enemyCoordinatorTargetFrequency = 20;
                enemyMoveCounter = 5;
                break;
        }
    }

    private static void ProcessEnemies()
    {
        //check if we win
        if (enemies.Count == 0)
        {
            YouWin();
        }

        //kill enemies hit by bullets
        CheckIfBulletsHitEnemies();

        //coordinator logic
        CoordinatorEnemyLogic();

        //enemy movement
        MoveTheEnemies();

        //drawing enemies
        DrawEnemies();

        //are you dead?
        CheckIfEnemiesWin();
    }

    //movement of the enemies
    private static void MoveTheEnemies()
    {
        //only if the enemyMoveFactor is < 0 we move the enemies - this way player moves faster than the enemies
        enemyMoveFactor -= 1;
        if (enemyMoveFactor < 0)
        {
            enemyMoveFactor = enemyMoveCounter;

            //checks if there are obstacles on the way
            ChangeDirectionBecauseOfObsticlesAndConsoleLimits();

            foreach (Enemy enemy in enemies)
            {
                //after the direction is changed we can safely move
                enemy.Move();
            }
        }
    }

    //checks if there are obstacles on the way or we are leaving the console
    private static void ChangeDirectionBecauseOfObsticlesAndConsoleLimits()
    {
        //for each enemy if the next position will hit obsticle change his direction
        //right and left just stops the enemy movement (direction[0] = 0)
        //up and down stops the movement (direction[1] = 0) and if direction[0] is also 0 reverses the movement by Y
        foreach (Enemy enemy in enemies)
        {
            if (enemy.Type == "coordinator")//the coordinator doesn't move
            {
                continue;
            }
        //console limits
        checkConsoleAgain:
            if (enemy.Direction[0] + enemy.X < 0 || enemy.Direction[0] + enemy.X > ConsoleHeightMax - 3)
            {
                enemy.Direction[0] *= (-1);
            }
            if (enemy.Direction[1] + enemy.Y < 0 || enemy.Direction[1] + enemy.Y > ConsoleWidthMax - 3)
            {
                enemy.Direction[1] *= (-1);
            }

            foreach (var obst in obstacles)
            {
                if (SourceHitsTarget(obst.y, obst.x, enemy.X + enemy.Direction[0], enemy.Y + enemy.Direction[1]))
                {
                    enemy.Direction[0] = rnd.Next(-1, 2);
                    enemy.Direction[1] = rnd.Next(-1, 2);
                    goto checkConsoleAgain;//16 lines up
                }
            }


        }
    }

    //all the coordinator logic is here
    private static void CoordinatorEnemyLogic()
    {
        //needs to run the first time - target the enemies onto player
        if (enemyInitialTargeting)
        {
            enemyInitialTargeting = false;
            enemyTargetX = player.y;
            enemyTargetY = player.x;
            GuideEachEnemy();
        }
        //both cases CoordinatorTargetsThePlayer() is called - if the coordinator is alive the player's coordinates are used
        //  otherwise the enemies just target the centre of the screen
        if (enemyCoordinatorIsAlive)
        {
            //these two control how often the coordinator targets you
            enemyCoordinatorTargetTimer -= enemyCoordinatorTargetFrequency;
            if (enemyCoordinatorTargetTimer < 0)
            {
                enemyCoordinatorTargetTimer = 1000;
                enemyTargetX = player.y;
                enemyTargetY = player.x;
                CoordinatorTargetsThePlayer();
            }
        }
        else
        {
            enemyTargetX = ConsoleHeightMax / 2;
            enemyTargetY = ConsoleWidthMax / 2;
            CoordinatorTargetsThePlayer();
        }
    }

    //sets the direction of each enemy
    private static void CoordinatorTargetsThePlayer()
    {
        //sets the target coords to match the player position
        if (enemyCoordinatorIsAlive)
        {
            //this is the red cross over the player
            AnimationTarget();

            //the coordinator's speech
            Console.SetCursorPosition(enemyCoordinatorCoordinates[1], enemyCoordinatorCoordinates[0] + 3);
            Console.ForegroundColor = ConsoleColor.White;
            Console.Write(enemyCoordinatorTalks[rnd.Next(0, enemyCoordinatorTalks.Length)]);
        }

        //change direction of each enemy
        GuideEachEnemy();
    }

    //this is the red cross over the enemy
    private static void AnimationTarget()
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.SetCursorPosition(player.x, player.y);
        Console.Write("\\");
        Console.SetCursorPosition(player.x + 2, player.y);
        Console.Write("/");
        Console.SetCursorPosition(player.x + 1, player.y + 1);
        Console.Write("X");
        Console.SetCursorPosition(player.x, player.y + 2);
        Console.Write("/");
        Console.SetCursorPosition(player.x + 2, player.y + 2);
        Console.Write("\\");
    }

    //the changing of the direction of each enemy
    private static void GuideEachEnemy()
    {
        foreach (Enemy enemy in enemies)
        {
            if (enemy.Type == "normal")
            {
                if (enemy.X < enemyTargetX)
                {
                    enemy.Direction[0] = 1;
                }
                else if (enemy.X > enemyTargetX)
                {
                    enemy.Direction[0] = -1;
                }
                else
                {
                    enemy.Direction[0] = 0;
                }

                if (enemy.Y < enemyTargetY)
                {
                    enemy.Direction[1] = 1;
                }
                else if (enemy.Y > enemyTargetY)
                {
                    enemy.Direction[1] = -1;
                }
                else
                {
                    enemy.Direction[1] = 0;
                }
            }
            else if (enemy.Type == "dummy")
            {
                if (rnd.Next(0, 2) == 0)
                {
                    if (enemy.X < enemyTargetX)
                    {
                        enemy.Direction[0] = 1;
                    }
                    else if (enemy.X > enemyTargetX)
                    {
                        enemy.Direction[0] = -1;
                    }
                    else
                    {
                        enemy.Direction[0] = 0;
                    }

                    if (enemy.Y < enemyTargetY)
                    {
                        enemy.Direction[1] = 1;
                    }
                    else if (enemy.Y > enemyTargetY)
                    {
                        enemy.Direction[1] = -1;
                    }
                    else
                    {
                        enemy.Direction[1] = 0;
                    }
                }
                else
                {
                    enemy.Direction = new int[] { 0, 0 };
                }
            }
        }
    }

    //draw
    private static void DrawEnemies()
    {
        //the moment when player kills coordinator enemies yell
        if (!enemyCoordinatorIsAlive && enemyWantToScreamIfTheirBossIsDead)
        {
            //this way they will only yell once
            enemyWantToScreamIfTheirBossIsDead = false;
            Console.ForegroundColor = ConsoleColor.White;
            foreach (Enemy enemy in enemies)
            {
                Console.SetCursorPosition(enemy.Y, enemy.X);
                Console.Write("NO!");
                Console.SetCursorPosition(enemy.Y, enemy.X + 1);
                Console.Write("OUR");
                Console.SetCursorPosition(enemy.Y, enemy.X + 2);
                Console.Write("BOS");
            }
            
            Console.Beep();
            System.Threading.Thread.Sleep(3000);
        }

        if (!enemyCoordinatorIsAlive)//krum -makes game more challenging//nice!!
        {
            if (enemyCoordinatorRespawnTime > 0)
            {
                enemyCoordinatorRespawnTime -= level;//
                if (level > 0)
                {
                    Console.SetCursorPosition(enemyCoordinatorCoordinates[1], enemyCoordinatorCoordinates[0] + 3);
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.Write(enemyCoordinatorRespawnTime/10);
                }
            }
            else
            {
                if (level > 0)
                {
                    Console.SetCursorPosition(enemyCoordinatorCoordinates[1], enemyCoordinatorCoordinates[0] + 3);
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.Write("   ");
                }
                GenerateCoordinatorEnemy();
                enemyWantToScreamIfTheirBossIsDead = true;
                enemyCoordinatorIsAlive = true;
            }
        }

        //just call Draw method from Enemy
        foreach (Enemy enemy in enemies)
        {
            enemy.Draw();
        }
    }

    //are enemies getting player
    private static void CheckIfEnemiesWin()
    {
        foreach (var enem in enemies)
        {
            //check the four corners of the player coordinates
            if (SourceHitsTarget(enem.X, enem.Y, player.y, player.x) ||
                SourceHitsTarget(enem.X, enem.Y + 2, player.y, player.x) ||
                SourceHitsTarget(enem.X + 2, enem.Y, player.y, player.x) ||
                SourceHitsTarget(enem.X + 2, enem.Y + 2, player.y, player.x))
            {
                GameOver();
            }
        }
    }

    //are bullets getting enemies
    private static void CheckIfBulletsHitEnemies()
    {
        //this will hold the still alive enemies
        List<Enemy> newList = new List<Enemy>();

        foreach (var enem in enemies)
        {
            //checks if the current enemy is alive
            bool alive = true;
            foreach (var bullet in Shots)
            {
                //only interested in live bullets
                if (bullet.alive)
                {
                    if (SourceHitsTarget(bullet.X, bullet.Y, enem.Y, enem.X))
                    {

                        Console.Beep(3300, 100);
                        enem.Life--;
                        bullet.alive = false;
                        if (enem.Life < 0)
                        {
                            //delete the enemy
                            enem.Die();
                            //mark the bullet as not alive
                            //the enemy is not alive
                            alive = false;
                            //checks score to give to player depending on type of enemy
                            if (enem.Type == "coordinator")
                            {
                                //delete the speech of the coordinator
                                Console.SetCursorPosition(enemyCoordinatorCoordinates[1], enemyCoordinatorCoordinates[0] + 3);
                                Console.ForegroundColor = ConsoleColor.Black;
                                Console.Write("    ");
                                playerTotalScore += enemyScoreGivvenForKillingCoordinatorEnemy * (level + 1);
                                //we no longer have coordinator
                                enemyCoordinatorIsAlive = false;
                            }
                            else if (enem.Type == "dummy")
                            {
                                playerTotalScore += enemyScoreGivvenForKillingDummyEnemy * (level + 1);
                            }
                            else if (enem.Type == "normal")
                            {
                                playerTotalScore += enemyScoreGivvenForKillingNormalEnemy * (level + 1);
                            }
                            break;
                        }
                    }
                }
            }
            //the enemy is not alive is used here
            if (alive)
            {
                newList.Add(enem);
            }
        }
        //update the list of enemies
        enemies = newList;
    }

    //checks if by a givven position X Y (Source) a target 3x3 is hit (needs the target topleft coord X Y )
    private static bool SourceHitsTarget(int sourceX, int sourceY, int targetX, int targetY)
    {
        if (targetX == sourceX || targetX + 1 == sourceX || targetX + 2 == sourceX)
        {
            if (targetY == sourceY || targetY + 1 == sourceY || targetY + 2 == sourceY)
            {
                return true;
            }
        }
        return false;
    }

    //enemy generation
    private static void GenerateEnemies()
    {
        ProcessGameDifficulty();

        GenerateNormalEnemies();

        GenerateDummyEnemies();

        GenerateCoordinatorEnemy();

        //saving the coordinator enemy position
        //enemyCoordinatorCoordinates = new int[] { enemies[enemies.Count - 1].X, enemies[enemies.Count - 1].Y }; moved to GenerateCoordinatorEnemy();
    }

    //only one coordinator created
    private static void GenerateCoordinatorEnemy()
    {
        //checks on wich side the coordinator will appear
        enemyCoordinatorIsAlive = true;//krum
        enemyCoordinatorRespawnTime = 1000;
        int determiner = rnd.Next(0, 4);
        switch (determiner)
        {
            //leftside
            case 0:
                enemies.Add(new Enemy(rnd.Next(1, ConsoleHeightMax - 4), 1, 0, 0, enemyhardness + 10, "coordinator"));
                break;
            //rigtside
            case 1:
                enemies.Add(new Enemy(rnd.Next(1, ConsoleHeightMax - 4), ConsoleWidthMax - 4, 0, 0, enemyhardness + 10, "coordinator"));
                break;
            //topside
            case 2:
                enemies.Add(new Enemy(1, rnd.Next(1, ConsoleWidthMax - 4), 0, 0, enemyhardness + 10, "coordinator"));
                break;
            //bottomside
            case 3:
                enemies.Add(new Enemy(ConsoleHeightMax - 4, rnd.Next(1, ConsoleWidthMax - 4), 0, 0, enemyhardness + 10, "coordinator"));
                break;
        }
        enemyCoordinatorCoordinates = new int[] { enemies[enemies.Count - 1].X, enemies[enemies.Count - 1].Y };
    }

    //the number of dummy enemies generated is enemyDummies var / 4
    //the variables in the for-cycles show on which side the enemy is created
    private static void GenerateDummyEnemies()
    {
        for (int i = 0; i < enemyDummies; i++)
        {
            switch (rnd.Next(0, 4))
            {
                case 0: enemies.Add(new Enemy(rnd.Next(1, ConsoleHeightMax - 4), 1, 0, 1, enemyhardness - 1, "dummy"));
                    break;
                case 1: enemies.Add(new Enemy(rnd.Next(1, ConsoleHeightMax - 4), ConsoleWidthMax - 4, 0, -1, enemyhardness - 1, "dummy"));
                    break;
                case 2: enemies.Add(new Enemy(1, rnd.Next(4, ConsoleWidthMax - 4), 1, 0, enemyhardness - 1, "dummy"));
                    break;
                case 3: enemies.Add(new Enemy(ConsoleHeightMax - 4, rnd.Next(1, ConsoleWidthMax - 4), -1, 0, enemyhardness - 1, "dummy"));
                    break;
            }
        }
    }

    //the number of normal enemies generated is enemyNormal var / 4
    //the variables in the for-cycles show on which side the enemy is created
    //type of enemy is not used - the constructor's default value for type is "normal"
    private static void GenerateNormalEnemies()
    {
        for (int i = 0; i < enemyNormal; i++)
        {
            switch (rnd.Next(0, 4))
            {
                case 0: enemies.Add(new Enemy(rnd.Next(1, ConsoleHeightMax - 4), 1, 0, 1, enemyhardness));
                    break;

                case 1: enemies.Add(new Enemy(rnd.Next(1, ConsoleHeightMax - 4), ConsoleWidthMax - 4, -1, 0, enemyhardness));
                    break;

                case 2: enemies.Add(new Enemy(1, rnd.Next(1, ConsoleWidthMax - 4), 0, 1, enemyhardness));
                    break;

                case 3: enemies.Add(new Enemy(ConsoleHeightMax - 4, rnd.Next(1, ConsoleWidthMax - 4), 0, -1, enemyhardness));
                    break;
            }
        }
    }


    #endregion
}